/*程序说明：基于UNO 本程序通过超声波判断距离实现舵机角度变化 并且通过定时器实现扫描超声波 实现闭盖时进行紫外线消杀（每工作10分钟休息10分钟） 单位cm*/
//当您使用Servo库时，开发板的9号和10号引脚的PWM功能是无法使用的。
/*注意事项：
（1）如果你使用了 MsTimer2 库， 则 pin11 和 pin3 就不能再用做 PWM 输出了! 因为该 pin3 和 pin11 的 PWM 是靠 timer2 帮忙的! (tone()也是)
（2）注意 Servo.h 库与 TimerOne 都是使用内部定时器 timer1 会影响pin 9, pin 10 的 PWM
（3）tone() 使用 timer2 定时器; 若使用 Tone 库的 Tone 对象(Tone 变量)也是优先使用 timer2 定时器，若用两个 Tone 变量则 timer1 也会被用掉， 用三个 Tone 则连控制 millis( )的 timer0 也会被用掉。
（4）别忘了， timer0 负责帮忙控制 pin 5 和 pin 6 的 PWM 输出。只要不去改变 timer 的 Prescaler 就不会影响其控制的 PWM pin， 但MsTimer2 库与 tone( )都会改变 Prescaler ! !*/

#include<Arduino.h>
#include <Servo.h>            //加载文件库
#include <MsTimer2.h>  //没安装的自己安装

 
#define limit_distance 15     //宏定义感应距离单位cm
#define uvcpin  10 //紫外线灯控制引脚（正）
#define worktime 600 //工作时间 单位10ms
#define resttime 600 //休息时间 单位10ms
#define pospin 9 //舵机引脚
#define posclose 120
int pos = 0; //舵机角度
Servo myservo; //设置伺服对象
const int trigpin = 2;  //超声波输出
const int echopin = 3;  //超声波输入
int posflag = 0; //判断盖子是否开启
int uvcflag = 0; //判断uvc是否开启
int uvctimeflag = 0; //判断uvc休息时间
volatile int pastflag = 0;//用于扫描后传递超声波距离比较信息
long int uvctime = 0; 
long int uvcnotime = 0;
volatile float distance; 
 
void scanTimer()//中断函数
{
  distance = 0;
  digitalWrite(trigpin,LOW);
  delayMicroseconds(2);
  digitalWrite(trigpin,HIGH);
  delayMicroseconds(10);
  digitalWrite(trigpin,LOW);
  distance = pulseIn(echopin,HIGH)/59.70;
  delay(10);  // 前面为超声波检测程序
  if(distance < limit_distance)
  {
     pastflag = 1;
  }
  else pastflag = 0;
}
 
void poscontrol()
{
  while(pastflag == 1) //判断距离确定是否开关
  {
    digitalWrite(uvcpin,LOW);
    myservo.write(posclose);
    delay(1000);	
    posflag = 1;
  } 
  if(posflag == 1)
  {
    for (pos = posclose; pos >= 0; pos -= 1)
    {
        myservo.write(pos);
        delay(15); 					
    }
    delay(100);
    posflag = 0;
  }
} 
 
void setup() {
  pinMode(trigpin,OUTPUT);
  pinMode(uvcpin,OUTPUT);
  pinMode(echopin,INPUT);
  myservo.attach(pospin, 500, 2500); //修正脉冲宽度
  myservo.write(0);//每次开启自动关闭盖子
  delay(500);
  scanTimer(); //每次启动先扫描一下
  MsTimer2::set(300, scanTimer); //设置中断，每1000ms进入一次中断服务程序 scanTimer()
  MsTimer2::start(); //开始计时_开启定时器中
}
 
void loop() {
  if(pastflag == 1)
  {
    poscontrol();  //调用舵机函数
   pastflag = 0;  //清除标志位
 }
  if(posflag == 0 && pastflag == 0)
  {
      digitalWrite(uvcpin,HIGH);
      uvcflag = 1;
  }
  else
  {
    uvcflag = 0;
    digitalWrite(uvcpin,LOW);
  }
  //每工作10分钟休息10分钟
  if(uvcflag == 1 && uvctimeflag == 0)
  {
    uvctime++;
    delay(10);
    if(uvctime >= worktime)
    {
      uvctime = 0;
      uvctimeflag = 1;
      digitalWrite(uvcpin,LOW);
      //break;
    }
    
  }
  if(uvctimeflag = 1 && pastflag == 0)
  {
    uvcnotime++;
    delay(10);
    if(uvcnotime >= resttime)
    {
      uvcnotime = 0;
      uvctimeflag = 0;
      digitalWrite(uvcpin,HIGH);
      //break;
    }
  }
} 